#include "assert.h"
#include "interrupt.h"
#include "ipi.h"
#include "sbi.h"
#include "timer.h"
#include "tinyprintf.h"

#define UNUSED(x) (void)(x)
static void stdout_putc(void *unused, char ch) { SBI_PUTCHAR(ch); }

extern unsigned long _start, _start_another;

void p_test(void) { tfp_printf("test\n"); }

volatile bool init = 0;
void main_another() {
  init_printf(0, stdout_putc);
  tfp_printf("hello world from hart1\n");
  table_val_set();
  enable_external_interrupt();
  enable_software_interrupt();
  interrupt_enable();
  struct hart_mask mask = {0b01, 0};
  send_ipi(&mask);
  while (1) {
  }
}

void main() {
  init_printf(0, stdout_putc);
  tfp_printf("hello world\n");
  // tfp_printf("hello world2\n");
  uint64 hartid = 0b00;
  struct sbiret ret = sbi_extcall(HSM, 2, hartid, 0, 0);
  assert(ret.error == 0);
  hartid = 0b01;
  ret = sbi_extcall(HSM, 2, hartid, 0, 0);
  assert(ret.error == 0);
  // hack, got the entry address (_start_another) in gdb
  ret = sbi_extcall(HSM, 0, hartid, (long)&_start_another, 0);
  assert(ret.error == 0);
  do {
    ret = sbi_extcall(HSM, 2, hartid, 0, 0);
  } while (ret.value != 0);
  assert(ret.error == 0);
  // p_test();
  // test irq
  table_val_set();
  enable_timer_interrupt();
  // enable_software_interrupt();
  enable_external_interrupt();
  // init_timer();
  interrupt_enable();
  // wait for interrupt from hart0
  asm volatile("wfi");
  struct hart_mask mask = {0b10, 0};
  send_ipi(&mask);
  while (1) {
  }
}
